﻿//#include<stdio.h>
//
//void sp(int* a)
//{
//	int b = 2;
//	a = &b;
//	*a = *a * 2;
//	printf("%d,", *a);
//}
//void main()
//{
//	int k = 3,*p = &k;
//	sp(p);
//	printf("%d,%d\n", k, *p);
//
//}
//
//
//#include<stdio.h>
//#include<stdbool.h>
//int main()
//{
//	int ture = 1;
//	bool flag = ture;      //_Bool=bool
//	if (flag)
//	{                              //布尔类型专门表示真假
//		printf("hehe\n");
//	}
//	return 0;
//}
//
//
//
////计算十个数字之中的最大值
//#include <stdio.h>
//int main()
//{
//	int arr[] = { -1,-2,-3,-4,-5,-6,-7,-8,-9,-10 };
//	int max = arr[0];//最大值                    
//	//细节
//	int i = 0;
//	int sz = sizeof(arr) / sizeof(arr[0]);   //计算元素个数
//	for (i = 1; i < sz; i++)
//	{
//		if (arr[i] > max)
//		{
//			max = arr[i];
//		}
//
//	}
//	printf("max=%d\n", max);
//	return 0;
//}
//
//
////在屏幕上输出9*9乘法口诀表
//#include<stdio.h>
//int main()
//{
//	int i = 0;
//	//确定打印九行
//	for (i + 1; i <= 9; i++)
//	{
//
//		//打印一行
//		int j = 1;
//		for (j = 1; j <= i; j++)
//		{
//			printf("%d*%d=%-2d ", i, j, i * j);//不对齐  -----2d--打印两位，不够两位空格代替
//			//2d右对齐，-2d左对齐
//
//		}
//		printf("\n");
//	}
//
//	return 0;
//}


//#include <stdio.h>
//#include <stdlib.h>
//#pragma warning (disable:4996)
//struct list
//{
//    int data;
//    struct list* next;
//};
//
//struct list* createlist(int data[], int n)
//{
//    struct list* head = 0, * p, * q;
//    int i;
//
//    head = (struct list*)malloc(sizeof(struct list));
//    head->data = data[0];
//    p = q = head;
//    for (i = 1; i < n; i++)
//    {
//        p = (struct list*)malloc(sizeof(struct list));
//        p->data = data[i]; q->next = p; q = p;
//    }
//    p->next = NULL;
//    return head;
//}
//
///**********found**********/
//int func(list* head)
//{
//    int pmax = head->data;
//    struct list* p = head->next;
//    while (p != NULL)
//    {
//        if (p->data > pmax) pmax = p->data;
//        /**********found**********/
//        p = p->next;
//    }
//    /**********found**********/
//    return pmax;
//}
//
//void main()
//{
//    int data[] = { 123, 21, 65, 789, 32, 310, 671, 651, 81, 101 }, pmax;
//
//    struct list* head;
//    head = createlist(data, 10);
//    pmax = func(head);
//    printf("Max=%d\n", pmax);
//}

//#include   <stdio.h>
//#include   <string.h>
//void NONO();
//long  fun(char* s)
//{
//	int len = strlen(s);
//	int cnt = 1;
//	long ret = 0;
//	int i;
//	for (i = len - 1; i >= 0; i--)
//	{
//		ret = ret * 10 + s[i];
//	}
//
//	return ret;
//}
//main()
//{
//	char  s[10];    long  r;
//	printf("请输入一个长度不超过9个字符的数字字符串 :  ");  gets(s);
//	r = fun(s);
//	printf(" r = %ld\n", r);
//	NONO();
//	getchar();
//}
//
//void NONO()
//{/* 本函数用于打开文件，输入数据，调用函数，输出数据，关闭文件。 */
//	FILE* fp, * wf;
//	int i;  long r;
//	char s[10], * p;
//
//	fp = fopen("in.dat", "r");
//	wf = fopen("out.dat", "w");
//	for (i = 0; i < 10; i++) {
//		fgets(s, 10, fp);
//		p = strchr(s, '\n');
//		if (p) *p = 0;
//		r = fun(s);
//		fprintf(wf, "%ld\n", r);
//	}
//	fclose(fp);
//	fclose(wf);
//}


/ class Person
//{
//public:
//	Person() { ++_count; }
//protected:
//	string _name; // 姓名
//public:
//	static int _count; // 统计人的个数。
//};
//int Person::_count = 0;
//class Student : public Person
//{
//protected:
//	int _stuNum; // 学号
//};
//class Graduate : public Student
//{
//protected:
//	string _seminarCourse; // 研究科目
//};
//void TestPerson()
//{
//	Student s1;
//	Student s2;
//	Student s3;
//	Graduate s4;
//	cout << " 人数 :" << Person::_count << endl;
//	Student::_count = 0;
//	cout << " 人数 :" << Person::_count << endl;
}



//class Person
//{
//public:
//	string _name; // 姓名
//};
//class Student : virtual public Person
//{
//protected:
//	int _num; //学号
//};
//class Teacher : virtual public Person
//{
//protected:
//	int _id; // 职工编号
//};
//class Assistant : public Student, public Teacher
//{
//protected:
//	string _majorCourse; // 主修课程
//};
//void Test()
//{
//	Assistant a;
//	a._name = "peter";
//}

//
//class Person
//{
//public:
//	string _name; // 姓名
//};
//class Student : public Person
//{
//protected:
//	int _num; //学号
//};
//class Teacher : public Person
//{
//protected:
//	int _id; // 职工编号
//};
//class Assistant : public Student, public Teacher
//{
//protected:
//	string _majorCourse; // 主修课程
//};
//void Test()
//{
//	// 这样会有二义性无法明确知道访问的是哪一个
//	Assistant a;
//	a._name = "peter";
//	// 需要显示指定访问哪个父类的成员可以解决二义性问题，但是数据冗余问题无法解决
//	a.Student::_name = "xxx";
//	a.Teacher::_name = "yyy";
//}




//class Person {
//public:
//	virtual void BuyTicket() { cout << "买票-全价" << endl; }
//};
//class Student : public Person {
//public:
//	virtual void BuyTicket() { cout << "买票-半价" << endl; }
//	/*注意：在重写基类虚函数时，派生类的虚函数在不加virtual关键字时，虽然也可以构成重写(因
//	为继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性),但是该种写法不是很规范，不建议
//	这样使用*/
//	/*void BuyTicket() { cout << "买票-半价" << endl; }*/
//};
//void Func(Person& p)
//{
//	p.BuyTicket();
//}
//int main()
//{
//	Person ps;
//	Student st;
//	Func(ps);
//	Func(st);
//	return 0;
//}
//


//class Student;
//class Person
//{
//public:
//	friend void Display(const Person& p, const Student& s);
//protected:
//	string _name; // 姓名
//};
//class Student : public Person
//{
//protected:
//	int _stuNum; // 学号
//};
//void Display(const Person& p, const Student& s)
//{
//	cout << p._name << endl;
//	cout << s._stuNum << endl;
//}
//void main()
//{
//	Person p;
//	Student s;
//	Display(p, s);
//}



//
//class Person
//{
//public:
//	Person() { ++_count; }
//protected:
//	string _name; // 姓名
//public:
//	static int _count; // 统计人的个数。
//};
//int Person::_count = 0;
//class Student : public Person
//{
//protected:
//	int _stuNum; // 学号
//};
//class Graduate : public Student
//{
//protected:
//	string _seminarCourse; // 研究科目
//};
//void TestPerson()
//{
//	Student s1;
//	Student s2;
//	Student s3;
//	Graduate s4;
//	cout << " 人数 :" << Person::_count << endl;
//	Student::_count = 0;
//	cout << " 人数 :" << Person::_count << endl;
}



//class Person
//{
//public:
//	string _name; // 姓名
//};
//class Student : virtual public Person
//{
//protected:
//	int _num; //学号
//};
//class Teacher : virtual public Person
//{
//protected:
//	int _id; // 职工编号
//};
//class Assistant : public Student, public Teacher
//{
//protected:
//	string _majorCourse; // 主修课程
//};
//void Test()
//{
//	Assistant a;
//	a._name = "peter";
//}



//class Person
//{
//protected:
//	string _name; // 姓名
//	string _sex;  // 性别
//	int _age; // 年龄
//};
//class Student : public Person
//{
//public:
//	int _No; // 学号
//};
//void Test()
//{
//	Student sobj;
//	 1.子类对象可以赋值给父类对象/指针/引用
//	Person pobj = sobj;
//	Person* pp = &sobj;
//	Person& rp = sobj;
//
//	2.基类对象不能赋值给派生类对象
//	sobj = pobj;
//
//	 3.基类的指针可以通过强制类型转换赋值给派生类的指针
//	pp = &sobj
//		Student * ps1 = (Student*)pp; // 这种情况转换时可以的。
//	ps1->_No = 10;
//
//	pp = &pobj;
//	Student* ps2 = (Student*)pp; // 这种情况转换时虽然可以，但是会存在越界访问的问题
//		ps2->_No = 10;
//}
//
//
// Student的_num和Person的_num构成隐藏关系，可以看出这样代码虽然能跑，但是非常容易混淆
//class Person
//{
//protected:
//	string _name = "小李子"; // 姓名
//	int _num = 111;   // 身份证号
//};
//class Student : public Person
//{
//public:
//	void Print()
//	{
//		cout << " 姓名:" << _name << endl;
//		cout << " 身份证号:" << Person::_num << endl;
//		cout << " 学号:" << _num << endl;
//	}
//protected:
//	int _num = 999; // 学号
//};
//void Test()
//{
//	Student s1;
//	s1.Print();
//};

// B中的fun和A中的fun不是构成重载，因为不是在同一作用域
// B中的fun和A中的fun构成隐藏，成员函数满足函数名相同就构成隐藏。
//class A
//{
//public:
//	void fun()
//	{
//		cout << "func()" << endl;
//	}
//};
//class B : public A
//{
//public:
//	void fun(int i)
//	{
//		A::fun();
//		cout << "func(int i)->" << i << endl;
//	}
//};
//void Test()
//{
//	B b;
//	b.fun(10);
//};


//class Person
//{
//public:
//	Person(const char* name = "peter")
//		: _name(name)
//	{
//		cout << "Person()" << endl;
//	}
//
//	Person(const Person& p)
//		: _name(p._name)
//	{
//		cout << "Person(const Person& p)" << endl;
//	}
//
//	Person& operator=(const Person& p)
//	{
//		cout << "Person operator=(const Person& p)" << endl;
//		if (this != &p)
//			_name = p._name;
//
//		return *this;
//	}
//
//	~Person()
//	{
//		cout << "~Person()" << endl;
//	}
//protected:
//	string _name; // 姓名
//};
//class Student : public Person
//{
//public:
//	Student(const char* name, int num)
//		: Person(name)
//		, _num(num)
//	{
//		cout << "Student()" << endl;
//	}
//
//	Student(const Student& s)
//		: Person(s)
//		, _num(s._num)
//	{
//		cout << "Student(const Student& s)" << endl;
//	}
//
//	Student& operator = (const Student& s)
//	{
//		cout << "Student& operator= (const Student& s)" << endl;
//		if (this != &s)
//		{
//			Person::operator =(s);
//			_num = s._num;
//		}
//		return *this;
//	}
//
//	~Student()
//	{
//		cout << "~Student()" << endl;
//	}
//protected:
//	int _num; //学号
//};
//void Test()
//{
//	Student s1("jack", 18);
//	Student s2(s1);
//	Student s3("rose", 17);
//	s1 = s3;
//}


//int main()
//{
//    lock_free::stack<int> st1;
//    lock::stack<int> st2;
//    std::mutex mtx;
//    int n = 1000000;
//
//    auto lock_free_stack = [&st1, n] {
//        for (size_t i = 0; i < n; i++)
//        {
//            st1.push(i);
//        }
//    };
//
//    auto lock_stack = [&st2, &mtx, n] {
//        for (size_t i = 0; i < n; i++)
//        {
//            std::lock_guard<std::mutex> lock(mtx);
//            st2.push(i);
//        }
//    };
//
//    // 4个线程分别使用无锁方式和有锁方式插入n个数据到栈中对比性能
//    size_t begin1 = clock();
//    std::vector<std::thread> threads1;
//    for (size_t i = 0; i < 4; i++)
//    {
//        threads1.emplace_back(lock_free_stack);
//    }
//    for (auto& th : threads1)
//        th.join();
//    size_t end1 = clock();
//
//    std::cout << end1 - begin1 << std::endl;
//
//    size_t begin2 = clock();
//    std::vector<std::thread> threads2;
//    for (size_t i = 0; i < 4; i++)
//    {
//        threads2.emplace_back(lock_stack);
//    }
//    for (auto& th : threads2)
//        th.join();
//    size_t end2 = clock();
//
//    std::cout << end2 - begin2 << std::endl;
//
//    return 0;
//}

//#include <atomic>
//#include <thread>
//#include <iostream>
//#include <vector>
//
//// 自旋锁（SpinLock）是一种忙等待的锁机制，适用于锁持有时间非常短的场景。
//// 在多线程编程中，当一个线程尝试获取已被其他线程持有的锁时，自旋锁会让该
//// 线程在循环中不断检查锁是否可用，而不是进入睡眠状态。这种方式可以减少上
//// 下文切换的开销，但在锁竞争激烈或锁持有时间较长的情况下，会导致CPU资源的浪费。
//// 以下是使用C++11实现的一个简单自旋锁示例：
//class SpinLock
//{
//private:
//    // ATOMIC_FLAG_INIT默认初始化为false
//    std::atomic_flag flag = ATOMIC_FLAG_INIT;
//public:
//    void lock()
//    {
//        // test_and_set将内部值设置为true，并且返回之前的值
//        // 第一个进来的线程将值原子的设置为true，返回false
//        // 后面进来的线程将原子的值设置为true，返回true，所以卡在这里空转，
//        // 直到第一个进去的线程unlock，clear，将值设置为false
//        while (flag.test_and_set(std::memory_order_acquire));
//    }
//
//    void unlock()
//    {
//        // clear将值原子的设置为false
//        flag.clear(std::memory_order_release);
//    }
//};
//
//// 测试自旋锁
//void worker(SpinLock& lock, int& sharedValue) {
//    lock.lock();
//    // 模拟一些工作
//    for (int i = 0; i < 1000000; ++i) {
//        ++sharedValue;
//    }
//    lock.unlock();
//}
//
//int main() {
//    SpinLock lock;
//    int sharedValue = 0;
//    std::vector<std::thread> threads;
//
//    // 创建多个线程
//    for (int i = 0; i < 4; ++i) {
//        threads.emplace_back(worker, std::ref(lock), std::ref(sharedValue));
//    }
//
//    // 等待所有线程完成
//    for (auto& thread : threads) {
//        thread.join();
//    }
//
//    std::cout << "Final shared value: " << sharedValue << std::endl;
//    return 0;
//}

/////////////////////////////////////////////////////////////////////////////////////////////

// condition_variable::notify_all
#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

//std::mutex mtx;
//std::condition_variable cv;
//bool ready = false;
//
//void print_id(int id) {
//    std::unique_lock<std::mutex> lck(mtx);
//    while (!ready)
//        cv.wait(lck);
//
//    // ...
//    std::cout << "thread " << id << '\n';
//}
//
//void go() {
//    std::unique_lock<std::mutex> lck(mtx);
//    ready = true;
//
//    // 通知所有阻塞在条件变量上的线程
//    cv.notify_all();
//}
//
//int main()
//{
//    std::thread threads[10];
//    // spawn 10 threads:
//    for (int i = 0; i < 10; ++i)
//        threads[i] = std::thread(print_id, i);
//
//    std::cout << "10 threads ready to race...\n";
//
//    std::this_thread::sleep_for(std::chrono::milliseconds(100));
//
//    go();                       // go!
//
//    for (auto& th : threads)
//        th.join();
//
//    return 0;
//}



//		std::cout << "[task b failed: mutex " << (x ? "foo" : "bar") << " locked]\n";
//	}
//}
//
//int main()
//{
//	std::thread th1(task_a);
//	std::thread th2(task_b);
//
//	th1.join();
//	th2.join();
//
//	return 0;
//}

// call_once example
//#include <iostream>       // std::cout
//#include <thread>         // std::thread, std::this_thread::sleep_for
//#include <chrono>         // std::chrono::milliseconds
//#include <mutex>          // std::call_once, std::once_flag
//
//int winner;
//void set_winner(int x) { winner = x; }
//std::once_flag winner_flag;
//
//void wait_1000ms(int id) {
//	// count to 1000, waiting 1ms between increments:
//	for (int i = 0; i < 100; ++i)
//		std::this_thread::sleep_for(std::chrono::milliseconds(1));
//	// claim to be the winner (only the first such call is executed):
//	std::call_once(winner_flag, set_winner, id);
//}

//int main()
//{
//	std::thread threads[10];
//	// spawn 10 threads:
//	for (int i = 0; i < 10; ++i)
//		threads[i] = std::thread(wait_1000ms, i + 1);
//
//	std::cout << "waiting for the first among 10 threads to count 1000 ms...\n";
//
//	for (auto& th : threads) th.join();
//	std::cout << "winner thread: " << winner << '\n';
//
//	return 0;
//}

//#include <atomic>
//#include <iostream>
//#include <thread>
//#include <vector>
//using namespace std;
//
//atomic<int> acnt;
////atomic_int acnt;
//int cnt;
//
//void Add1(atomic<int>& cnt)
//{
//    int old = cnt.load();
//    // 如果cnt的值跟old相等，则将cnt的值设置为old+1，并且返回true，这组操作是原子的。
//    // 那么如果在load和compare_exchange_weak操作之间cnt对象被其他线程改了
//    // 则old和cnt不相等，则将old的值改为cnt的值，并且返回false。
//    //while (!atomic_compare_exchange_weak(&cnt, &old, old + 1));
//    while (!cnt.compare_exchange_weak(old, old + 1));
//}
//
//void f()
//{
//    for (int n = 0; n < 100000; ++n)
//    {
//        //++acnt;
//        // Add1的用CAS模拟atomic的operator++的原子操作
//        Add1(acnt);
//
//        ++cnt;
//    }
//}

//int main()
//{
//    std::vector<thread> pool;
//    for (int n = 0; n < 4; ++n)
//        pool.emplace_back(f);
//
//    for (auto& e : pool)
//        e.join();
//
//    cout << "原子计数器为 " << acnt << '\n'
//        << "非原子计数器为 " << cnt << '\n';
//
//    return 0;
//}

//struct Date
//{
//    int _year = 1;
//    int _month = 1;
//    int _day = 1;
//};
//
//template<class T>
//void check()
//{
//    cout << typeid(T).name() << endl;
//    cout << std::is_trivially_copyable<T>::value << endl;
//    cout << std::is_copy_constructible<T>::value << endl;
//    cout << std::is_move_constructible<T>::value << endl;
//    cout << std::is_copy_assignable<T>::value << endl;
//    cout << std::is_move_assignable<T>::value << endl;
//    cout << std::is_same<T, typename std::remove_cv<T>::type>::value << endl
//        << endl;
//}
//
//int main()
//{
//     check<int>();
//     check<double>();
//     check<int*>();
//     check<Date>();
//     check<Date*>();
//     check<string>();
//     check<string*>();
//
//    return 0;
//}

//#include <atomic>         // std::atomic
//#include <thread>         // std::thread
//#include <vector>         // std::vector
//
//// a simple global linked list:
//struct Node { int value; Node* next; };
//std::atomic<Node*> list_head(nullptr);
//
//void append(int val) {     // append an element to the list
//	std::this_thread::sleep_for(std::chrono::seconds(1));
//
//	Node* oldHead = list_head.load();
//	Node* newNode = new Node{ val,oldHead };
//
//	// what follows is equivalent to: list_head = newNode, but in a thread-safe way:
//	while (!list_head.compare_exchange_weak(oldHead, newNode))
//		newNode->next = oldHead;
//}
//
//int main()
//{
//	// spawn 10 threads to fill the linked list:
//	std::vector<std::thread> threads;
//	for (int i = 0; i < 10; ++i) 
//		threads.push_back(std::thread(append, i));
//
//	for (auto& th : threads)
//		th.join();
//
//	// print contents:
//	for (Node* it = list_head; it != nullptr; it = it->next)
//		std::cout << ' ' << it->value;
//	std::cout << '\n';
//
//	// cleanup:
//	Node* it; while (it = list_head) { list_head = it->next; delete it; }
//
//	return 0;
//}

//#include <iostream>       // std::cout
//#include <atomic>         // std::atomic
//#include <thread>         // std::thread
//#include <mutex>          // std::thread
//#include <vector>         // std::vector
//
//template<typename T>
//struct node
//{
//    T data;
//    node* next;
//    node(const T& data) : data(data), next(nullptr) {}
//};
//
//namespace lock_free
//{
//    template<typename T>
//    class stack
//    {
//    public:
//        std::atomic<node<T>*> head = nullptr;
//    public:
//        void push(const T& data)
//        {
//            node<T>* new_node = new node<T>(data);
//
//            // 将 head 的当前值放到 new_node->next 中
//            new_node->next = head.load(std::memory_order_relaxed);
//
//            // 现在令 new_node 为新的 head ，但如果 head 不再是
//            // 存储于 new_node->next 的值（某些其他线程必须在刚才插入结点）
//            // 那么将新的 head 放到 new_node->next 中并再尝试
//            while (!head.compare_exchange_weak(new_node->next, new_node,
//                std::memory_order_release,
//                std::memory_order_relaxed))
//                ; // 循环体为空
//        }
//    };
//}
//
//namespace lock
//{
//    template<typename T>
//    class stack
//    {
//    public:
//        node<T>* head = nullptr;
//
//        void push(const T& data)
//        {
//            node<T>* new_node = new node<T>(data);
//            new_node->next = head;
//            head = new_node;
//        }
//    };
//}

//int main()
//{
//    int x = 0;
//    mutex mtx;
//
//    // 将上面的代码改成使用lambda捕获外层的对象，也就可以不用传参数，间接解决了上面的问题
//    auto Print = [&x, &mtx](size_t n) {
//        mtx.lock();
//        for (size_t i = 0; i < n; i++)
//        {
//            ++x;
//        }
//        mtx.unlock();
//    };
//
//    thread t1(Print, 1000000);
//    thread t2(Print, 2000000);
//
//    t1.join();
//    t2.join();
//    cout << x << endl;
//    return 0;
//}

//std::timed_mutex mtx;
//void fireworks(int i)
//{
//	//std::cout << i;
//	// waiting to get a lock: each thread prints "-" every 200ms:
//	while (!mtx.try_lock_for(std::chrono::milliseconds(1000)))
//	{
//		std::cout << "-";
//	}
//	std::cout << i;
//
//	// got a lock! - wait for 1s, then this thread prints "*"
//	std::this_thread::sleep_for(std::chrono::milliseconds(5000));
//	std::cout << "*\n";
//
//	mtx.unlock();
//}

//int main()
//{
//	//std::thread threads[2];
//	vector<std::thread> threads(2);
//
//
//	// 利用移动赋值的方式，将创建的临时对象(右值对象)移动赋值给创建好的空线程对象
//	for (int i = 0; i < 2; ++i)
//		threads[i] = std::thread(fireworks, i);
//
//	for (auto& th : threads)
//		th.join();
//
//	return 0;
//}

//int main()
//{
//	int x = 0;
//	mutex mtx;
//	auto Print = [&x, &mtx](size_t n) {
//		{
//			lock_guard<mutex> lock(mtx);
//			//LockGuard<mutex> lock(mtx);
//			//mtx.lock();
//			for (size_t i = 0; i < n; i++)
//			{
//				++x;
//			}
//			//mtx.unlock();
//		}
//
//		for (size_t i = 0; i < 10; i++)
//		{
//			cout << x << endl;
//		}
//	};
//
//	thread t1(Print, 1000000);
//	thread t2(Print, 2000000);
//	t1.join();
//	t2.join();
//	cout << x << endl;
//
//	return 0;
//}

// std::lock example
#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <mutex>          // std::mutex, std::lock

//std::mutex foo, bar;
//
//void task_a() {
//	std::this_thread::sleep_for(std::chrono::seconds(1));
//
//	//foo.lock();
//	//bar.lock(); // replaced by:
//
//	std::lock(foo, bar);
//	std::cout << "task a\n";
//	foo.unlock();
//	bar.unlock();
//}
//
//void task_b() {
//	std::this_thread::sleep_for(std::chrono::seconds(1));
//
//	//bar.lock(); 
//	//foo.lock(); // replaced by:
//
//	std::lock(bar, foo);
//	std::cout << "task b\n";
//	bar.unlock();
//	foo.unlock();
//}
//
//int main()
//{
//	std::thread th1(task_a);
//	std::thread th2(task_b);
//
//	th1.join();
//	th2.join();
//
//	return 0;
//}

// std::lock example
//#include <iostream>       // std::cout
//#include <thread>         // std::thread
//#include <mutex>          // std::mutex, std::try_lock
//
//std::mutex foo, bar;
//
//void task_a() {
//	foo.lock();
//	bar.lock();
//	std::cout << "task a\n";
//	// ...
//	foo.unlock();
//	bar.unlock();
//}
//
//void task_b() {
//	int x = try_lock(bar, foo);
//	if (x == -1) {
//		std::cout << "task b\n";
//		// ...
//		bar.unlock();
//		foo.unlock();
//	}
//	else {
//		std::cout << "[task b failed: mutex " << (x ? "foo" : "bar") << " locked]\n";
//	}
//}
//
//int main()
//{
//	std::thread th1(task_a);
//	std::thread th2(task_b);
//
//	th1.join();
//	th2.join();
//
//	return 0;
//}